import type { NativeMediaType } from '@atlaskit/pragmatic-drag-and-drop/dist/types/internal-types'
import type { Ref } from 'vue'
/**
 * @用途 拖拽
 * @author 黄敏
 * @创建时间 2025-08-19 08:06
 **/
import { draggable } from '@atlaskit/pragmatic-drag-and-drop/element/adapter'
import { pointerOutsideOfPreview } from '@atlaskit/pragmatic-drag-and-drop/element/pointer-outside-of-preview'
import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview'

interface UseDragParams<Data extends Record<string, unknown>> {
  // 标签页拖拽元素
  el: Ref<HTMLElement | undefined>
  // 创建拖拽数据
  dragData: Data | ((isExternal?: boolean) => Data)
  /** 用于标识拖拽数据的唯一类型，确保类型安全 */
  dragType: Exclude<NativeMediaType, 'text/uri-list' | 'text/plain' | 'text/html' | 'Files'>
  /** 拖拽手柄元素的DOM引用, 不传则默认为el */
  dragEl?: Ref<HTMLElement | undefined>
  /** 拖拽预览偏移量配置 */
  previewOffset?: { x: string; y: string }
  /** 是否开启原生拖曳 */
  nativeDrag?: boolean
  /** 禁止拖拽 */
  noDrag?: boolean
}

/**
 * 边栏标签页拖拽状态类型
 */
export type TabDragState =
  | { type: 'idle' }
  | { type: 'preview'; container: HTMLElement }
  | { type: 'dragging' }

export function useDragHandle<Data extends Record<string, unknown>>({
  el,
  dragEl,
  nativeDrag,
  noDrag,
  dragData,
  previewOffset,
  dragType
}: UseDragParams<Data>) {
  /** 默认空闲状态 */
  const IDLE_STATE: TabDragState = { type: 'idle' }

  /** 当前标签页的拖拽状态 */
  const dragState = shallowRef<TabDragState>(IDLE_STATE)

  /** 清理函数，用于取消拖拽相关的事件监听器 */
  let cleanupDragListeners = () => {}

  onMounted(() => {
    if (!el.value || noDrag) return // 元素引用无效或禁止拖拽，退出

    cleanupDragListeners = draggable({
      element: el.value,
      dragHandle: dragEl?.value,

      /**
       * 获取拖拽时携带的初始数据
       * @returns 包含标签页信息的拖拽数据对象
       */
      getInitialData() {
        return {
          [dragType]: typeof dragData === 'function' ? dragData() : { ...dragData }
        }
      },

      /**
       * 获取外部拖拽的初始数据（跨窗口拖拽）
       * @returns 外部拖拽数据对象
       */
      getInitialDataForExternal: () => {
        return nativeDrag
          ? {
              [dragType]: JSON.stringify(typeof dragData === 'function' ? dragData() : dragData)
            }
          : {}
      },

      /**
       * 生成自定义拖拽预览
       * 设置预览的偏移量和渲染逻辑
       */
      onGenerateDragPreview({ nativeSetDragImage }) {
        setCustomNativeDragPreview({
          nativeSetDragImage,
          getOffset: pointerOutsideOfPreview(previewOffset ?? { x: '0', y: '0' }),
          render({ container }) {
            // 设置预览状态，传入预览容器
            dragState.value = { type: 'preview', container }
          }
        })
      },

      /**
       * 拖拽开始时的回调
       * 更新状态为拖拽中
       */
      onDragStart() {
        dragState.value = { type: 'dragging' }
      },

      /**
       * 拖拽结束时的回调
       * 重置状态为空闲
       */
      onDrop() {
        dragState.value = IDLE_STATE
      }
    })
  })

  onUnmounted(() => {
    cleanupDragListeners()
  })

  return {
    dragState
  }
}
